package com.reverie.controller;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.reverie.common.pojo.CommonPageReq;
import com.reverie.common.pojo.CommonResult;
import com.reverie.config.DateTimeFormatterConstants;
import com.reverie.config.util.DateUtils;
import com.reverie.dto.req.*;
import com.reverie.dto.resp.AnalysisData;
import com.reverie.dto.resp.ExportOrderModel;
import com.reverie.dto.resp.MakeGroupModel;
import com.reverie.dto.resp.StatisticModel;
import com.reverie.entity.OrderGoods;
import com.reverie.entity.OrderInfo;
import com.reverie.service.ICouponLogService;
import com.reverie.service.ICouponService;
import com.reverie.service.IOrderInfoService;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author Rui.Zhou
 * @since 2024-02-03
 */
@RestController
@RequestMapping("/order")
public class OrderInfoController {

    private final IOrderInfoService orderInfoService;
    private final ICouponLogService couponLogService;
    private final ICouponService couponService;

    public OrderInfoController(IOrderInfoService orderInfoService, ICouponLogService couponLogService, ICouponService couponService) {
        this.orderInfoService = orderInfoService;
        this.couponLogService = couponLogService;
        this.couponService = couponService;
    }


    @PostMapping("summaryForChart")
    public CommonResult<List<Map>> summaryForChart(@RequestBody ChartParam chartParam){
        return CommonResult.data(orderInfoService.summaryForChart(chartParam));
    }

    @PostMapping("save")
    public CommonResult<Boolean> onSave(@RequestBody OrderInfo orderInfo) {
        return CommonResult.data(orderInfoService.onSave(orderInfo));
    }

    @PostMapping("sureOrder")
    public CommonResult<Boolean> sureOrder(@RequestBody OrderInfo orderInfo) {
        OrderInfo order = orderInfoService.getById(orderInfo.getOrderId());
        order.setPackId(true);
        return CommonResult.data(orderInfoService.updateById(order));
    }

    @PostMapping("cancel")
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Boolean> cancel(@RequestBody OrderInfo orderInfo) {
        OrderInfo order = orderInfoService.getById(orderInfo.getOrderId());
        order.setOrderStatus(8);

        if (StringUtils.hasLength(orderInfo.getCouponId())) {
            couponLogService.deleteByUserIdAndOrderId(orderInfo.getUserId(), orderInfo.getOrderId());
            couponService.cancelOrder(orderInfo.getCouponId());
        }

        return CommonResult.data(orderInfoService.updateById(order));
    }

    @PostMapping("queryPage")
    public CommonResult<Page<OrderInfo>> queryPage(@RequestBody CommonPageReq<OrderQueryParam> queryPageParam) {
        return CommonResult.data(orderInfoService.queryPage(queryPageParam));
    }

    @PostMapping("analysis")
    public CommonResult<AnalysisData> analysis(@RequestBody OrderQueryParam queryPageParam) {
        return CommonResult.data(orderInfoService.analysis(queryPageParam));
    }

    @PostMapping("allocation")
    public CommonResult<Boolean> allocation(@RequestBody DisShippingParam disShippingParam) {
        return CommonResult.data(orderInfoService.allocation(disShippingParam));
    }

    @PostMapping("salesStatisticsByDateRange")
    public CommonResult<List<StatisticModel>> salesStatisticsByDateRange(@RequestBody OrderQueryParam queryPageParam) {
        return CommonResult.data(orderInfoService.salesStatisticsByDateRange(queryPageParam));
    }

    @PostMapping("salesStatisticsByDay")
    public CommonResult<List<StatisticModel>> salesStatisticsByDay(@RequestBody OrderQueryParam queryPageParam) {
        return CommonResult.data(orderInfoService.salesStatisticsByDay(queryPageParam));
    }

    @GetMapping("exportList")
    public void exportList(OrderQueryParam queryParam, HttpServletResponse response) throws IOException {
        List<OrderInfo> orderList = orderInfoService.queryExportList(queryParam);

        List<ExportOrderModel> exportOrderModelList = new ArrayList<>();
        orderList.forEach(orderItem -> {
            List<OrderGoods> goodsList = orderItem.getGoodList();
            if(!CollectionUtils.isEmpty(goodsList)){
                goodsList.forEach(orderGoodsItem -> {
                    ExportOrderModel exportOrderModel = new ExportOrderModel();
                    BeanUtils.copyProperties(orderItem, exportOrderModel);
                    String addTimeText = DateUtils.formatLongTime(orderItem.getAddTime() * 1000);
                    exportOrderModel.setAddTimeText(addTimeText);
                    exportOrderModel.setShippingTime(DateTimeFormatterConstants.DATE_FORMAT.format(orderItem.getShippingDay()) + " " + orderItem.getShippingHour() + ":00");
                    exportOrderModel.setConAddress(orderItem.getCityName() + orderItem.getDistrictName() + orderItem.getAddress());
                    exportOrderModel.setGoodName(orderGoodsItem.getGoodsName());
                    exportOrderModel.setGoodsAttr(orderGoodsItem.getGoodsAttr());
                    exportOrderModel.setGoodsNumber(orderGoodsItem.getGoodsNumber().intValue());
                    exportOrderModel.setGoodsPrice(orderGoodsItem.getGoodsPrice().multiply(new BigDecimal(orderGoodsItem.getGoodsNumber())));
                    exportOrderModelList.add(exportOrderModel);
                });
            }
        });
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("订单导出" + DateTimeFormatterConstants.DATETIME_FORMAT.format(LocalDateTime.now()), "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), ExportOrderModel.class).sheet("订单列表").doWrite(exportOrderModelList);
    }

    @PostMapping("makeGood")
    public CommonResult<Object> makeGood(@RequestBody MakeGoodParam makeGoodParam) {
        String hour = makeGoodParam.getHour();
        String type = "";
        if (hour.contains("08")) {
            type = "之前";
        }else if (hour.contains("19")) {
            type = "之后";
        }
        int startHour = 8;
        int endHour = 0;
        if (type.equalsIgnoreCase("之前")) {
            endHour = 14;
        } else if (type.equalsIgnoreCase("之后")) {
            startHour = 14;
            endHour = 21;
        }
        List<OrderInfo> orderList = orderInfoService.selectMakeGoods(startHour, endHour);
        if (!CollectionUtils.isEmpty(orderList)) {
            orderList.forEach(orderInfo -> {
                orderInfoService.updateMakeGood(orderInfo.getOrderId(), makeGoodParam.getGoodsSn(), makeGoodParam.getGoodsAttr());
            });
        }

        return CommonResult.data(null);
    }

    @PostMapping("queryProductMakeGoods")
    public CommonResult<List<MakeGroupModel>> queryProductMakeGoods(@RequestBody MakeQueryParam makeQueryParam) {
        List<OrderGoods> orderGoods = orderInfoService.queryProductMakeGoods(makeQueryParam);
        if (CollectionUtils.isEmpty(orderGoods)) {
            return CommonResult.data(new ArrayList<>());
        }

        List<MakeGroupModel> orderGoodModelList = new ArrayList<>();
        Map<String, List<OrderGoods>> dateOrderGoodMap = orderGoods.stream().collect(Collectors.groupingBy(item -> {
            if (item.getShippingHour() >= 8 && item.getShippingHour() < 14) {
                return "08:00 ~ 14:00";
            } else if (item.getShippingHour() >= 14) {
                return "14:00 ~ 19:00";
            } else {
                return "";
            }
        }));
        dateOrderGoodMap.forEach((hourName, goodList) -> {
            MakeGroupModel makeGroupModel = new MakeGroupModel();
            makeGroupModel.setId(hourName);
            makeGroupModel.setName(hourName);
            makeGroupModel.setMaked(true);
            makeGroupModel.setCount(goodList.size());
            makeGroupModel.setSortId(hourName.contains("08") ? 1 : 2);

            Map<Integer, List<OrderGoods>> orderGoodIdMap = goodList.stream().collect(Collectors.groupingBy(OrderGoods::getGoodsId));
            List<MakeGroupModel> goodModelList = new ArrayList<>();
            Map<Integer,Integer> goodRowSpan = new HashMap<>();
            orderGoodIdMap.forEach((goodId,goods)-> {
                String goodsName = goods.get(0).getGoodsName();
                goodsName = goodsName.replaceAll("\\(草莓啵啵口味\\)","");
                goodsName = goodsName.replaceAll("\\(巧克力口味\\)","");
                Map<String, List<OrderGoods>> orderGoodAttrMap = goods.stream().sorted(Comparator.comparing(OrderGoods::getGoodsAttr)).collect(Collectors.groupingBy(OrderGoods::getGoodsAttr));
                String finalGoodsName = goodsName;
                orderGoodAttrMap.keySet().stream().sorted().forEach(goodAttr -> {
                    List<OrderGoods> goodAttrList = orderGoodAttrMap.get(goodAttr);
                    Map<String, List<OrderGoods>> orderGoodFlovarMap = goodAttrList.stream().sorted(Comparator.comparing(OrderGoods::getGoodsAttr)).collect(Collectors.groupingBy(OrderGoods::getFlavorName));
                    orderGoodFlovarMap.forEach((flavorName,flavorList) -> {
                        MakeGroupModel goodModel = new MakeGroupModel();
                        goodModel.setName(finalGoodsName + (StringUtils.hasLength(flavorName) ? "(" + flavorName + ")" : ""));
                        if(!goodRowSpan.containsKey(goodId)){
                            goodModel.setRowSpan(orderGoodAttrMap.size());
                            goodRowSpan.put(goodId,orderGoodAttrMap.size());
                        }
                        long sum = flavorList.stream().mapToLong(OrderGoods::getGoodsNumber).sum();
                        goodModel.setCount((int) sum);
                        long madeCount = flavorList.stream().filter(goodItem -> goodItem.getSendNumber() != null && goodItem.getSendNumber() > 0).mapToInt(OrderGoods::getSendNumber).sum();
                        goodModel.setMaked(sum == madeCount);
                        goodModel.setMakeNumber((int) madeCount);
                        goodModel.setHour(hourName);
                        goodModel.setFlavorName(flavorName);
                        goodModel.setGoodsSn(goodId.toString());
                        goodModel.setGoodsAttr(goodAttr);
                        goodModel.setId(hourName + "_" + finalGoodsName + "_" + goodAttr + "_" + goodId);
                        goodModelList.add(goodModel);
                    });
                });
            });

//            Map<String, List<OrderGoods>> orderGoodMap = goodList.stream().collect(Collectors.groupingBy(t -> t.getGoodsName() + "_" + t.getGoodsAttr() + "_" + t.getGoodsId()));
//            List<MakeGroupModel> goodModelList = new ArrayList<>();
//            orderGoodMap.forEach((goodInfo, goodItems) -> {
//                MakeGroupModel goodModel = new MakeGroupModel();
//                String[] keys = goodInfo.split("_");
//                goodModel.setName(keys[0] + " （" + keys[1] + "）");
//                long sum = goodItems.stream().mapToLong(OrderGoods::getGoodsNumber).sum();
//                goodModel.setCount((int) sum);
//                long madeCount = goodItems.stream().filter(goodItem -> goodItem.getSendNumber() != null && goodItem.getSendNumber() > 0).mapToInt(OrderGoods::getSendNumber).sum();
//                goodModel.setMaked(sum == madeCount);
//                goodModel.setHour(hourName);
//                if(keys.length >= 3){
//                    goodModel.setGoodsSn(keys[2]);
//                }
//                goodModel.setGoodsAttr(keys[1]);
//                goodModel.setId(hourName + "_" + goodInfo);
//                goodModelList.add(goodModel);
//            });
            makeGroupModel.setChildren(goodModelList);
            orderGoodModelList.add(makeGroupModel);
        });

        List<MakeGroupModel> finalMakeGoodModelList = orderGoodModelList.stream().sorted(Comparator.comparing(MakeGroupModel::getSortId)).collect(Collectors.toList());
        return CommonResult.data(finalMakeGoodModelList);
    }
}
